package com.example.practiceopenglforyuv;

import android.media.Image;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;

/**
 * name : Tools
 * time : 2019.11.7
 */

public class MTools {
    /**
     * Global Variable
     */
    // for log
    private static final String tag = "_" + "MTools";

    /**
     * to get byte[](NV21) form image(YUV420)
     * @param image     the yuv420 of image
     * @return          the nv21 of byte[]
     */
    static byte[] imageYUV420ToNV21(Image image) {
        int w = image.getWidth();
        int h = image.getHeight();
        byte[] nv21Bytes = new byte[w * h * 3 / 2];
        Image.Plane[] planes = image.getPlanes();
        for (int i=0; i<3; i++) {
            int rowStride = planes[i].getRowStride();
            int pixelStride = planes[i].getPixelStride();
            ByteBuffer buffer = planes[i].getBuffer();
            byte[] bytes = new byte[buffer.capacity()];
            buffer.get(bytes);
            int srcIndex = 0;
            int dctIndex = 0;
            if (i == 0) {
                System.arraycopy(bytes, dctIndex, nv21Bytes, 0, w * h);
            } else if (i == 1) {
                for (int j=0; j<w*h/4; j++) {
                    nv21Bytes[w*h + dctIndex*2 + 1] = bytes[srcIndex];
                    dctIndex += 1;
                    srcIndex += pixelStride;
                }
            } else {
                for (int j=0; j<w*h/4; j++) {
                    nv21Bytes[w*h + dctIndex*2] = bytes[srcIndex];
                    dctIndex += 1;
                    srcIndex += pixelStride;
                }
            }
        }
        return nv21Bytes;
    }

    /**
     * to save image data by appending
     * @param path      the path of saving image data
     * @param bytes     the image data
     */
    static void saveImageByAppend(String path, byte[] bytes) {
        File file = new File(path);
        if(! file.exists()){
            // create file
            try{
                FileOutputStream out = new FileOutputStream(file);
                out.write(bytes);
                out.close();
            }catch (IOException e){
                Log.e(tag,"create file fail !");
                e.printStackTrace();
            }
        } else{
            // append data
            try{
                RandomAccessFile randomFile = new RandomAccessFile(file,"rw");
                long fileLength = randomFile.length();
                randomFile.seek(fileLength);
                randomFile.write(bytes);
                randomFile.close();
            } catch (IOException e) {
                Log.e(tag,"open append file fail !");
                e.printStackTrace();
            }
        }
    }

    /**
     * read image data(YV12) from image file
     * @param path      the path of reading image data
     * @param y         the y plane of image data
     * @param u         the u plane of image data
     * @param v         the v plane of image data
     * @param w         the width of image data
     * @param h         the height of image data
     */
    static void loadImageFormYV12(String path, byte[] y, byte[] u, byte[] v, int w, int h) {
        File file = new File("/sdcard/" + "gf_a_1920x1080.YV12");
        if (! file.exists()) {
            Log.e(tag, "file is not exist !");
        } else {
            try {
                FileInputStream in = new FileInputStream(file);
                in.read(y);
                in.read(u);
                in.read(v);
                in.close();
            } catch (FileNotFoundException e) {
                Log.e(tag, "found file fail !");
                e.printStackTrace();
            } catch (IOException e) {
                Log.e(tag, "read file fail !");
                e.printStackTrace();
            }
        }
    }
}
